#include "ScenePrecompiled.hxx"
#include "SceneChild.hxx"
#include "Scene.hxx"

#include "InternalSceneChildImpl.hxx"

void Eifersucht::SceneChild::InternalRestart()
{
	//InternalRelease();

	if ( !m_pImpl )
	{
		m_pImpl = new _Internal_impl(this);
	}
}

void Eifersucht::SceneChild::InternalRelease()
{
	Safe_Delete( m_pImpl );
}

Eifersucht::SceneChild::SceneChild( _In_opt_ Eifersucht::SceneChildPtr pChild ) : 
	m_pParentScene(nullptr),
	m_pParentChild(nullptr),
	m_pContext(nullptr),
	m_pImpl(nullptr)
{
	//PrintToDebugWindowOnly8(
	//	"Eifersucht. SceneChild. "
	//	"Creating scene child."
	//	);

	InternalRestart();
	SetParentChild( pChild );
}

Eifersucht::SceneChild::~SceneChild()
{
	//PrintToDebugWindowOnly8( 
	//	"Eifersucht. SceneChild. "
	//	"Destroying scene child." 
	//	);

	InternalRelease();
	for ( auto pChild : m_Children )
	{
		Safe_Delete(pChild);
	}

	m_Name.clear();
	m_Children.clear();
	Safe_Delete(m_pContext);
}

void Eifersucht::SceneChild::ReleaseExternalResourcesRecursively()
{
	static _Short_dbg_msg s_szMsg;
	PrintToCharArray(s_szMsg, "Eifersucht. SceneChild. Releasing external resources.");
	PrintToDebugWindowOnly8(s_szMsg);

	if ( m_pContext ) m_pContext->ReleaseExternalResources();
	Safe_Delete( m_pImpl );

	for ( auto pChild : m_Children )
	{
		pChild->ReleaseExternalResourcesRecursively();
	}
}

Eifersucht::SceneChild::ContextType Eifersucht::SceneChild::GetChildContextType()
{
	if ( m_pContext )
	{
		return m_pContext->GetContextType();
	}
	else
	{
		return ContextType::Unknown;
	}
}

bool Eifersucht::SceneChild::IsRootChild() const
{
	// return m_pParentChild == nullptr;
	return m_bIsRootChild;
}

void Eifersucht::SceneChild::SetParentChild( _In_opt_ SceneChildPtr pChild )
{
	if ( pChild )
	{
		m_pParentChild = pChild;
		m_bIsRootChild = false;
	}
	else
	{
		m_pParentChild = nullptr;
		m_bIsRootChild = true;
	}
}

Eifersucht::SceneChildPtr Eifersucht::SceneChild::GetParentChild()
{
	return m_pParentChild;
}

// Parent scene access

void Eifersucht::SceneChild::SetParentScene( _In_opt_ ScenePtr pScene )
{
	m_pParentScene = pScene;
}

Eifersucht::ScenePtr Eifersucht::SceneChild::GetParentScene()
{
	return m_pParentScene;
}

Eifersucht::String8 Eifersucht::SceneChild::GetName() const
{
	return m_Name;
}

Eifersucht::SceneChildPtr Eifersucht::SceneChild::FindById( 
	_In_ Eifersucht::uint32 uChildId, 
	_In_opt_ bool bRecursively 
	)
{
	auto pChild = this; auto uId = pChild->UniqueId(); 
	if ( uId == uChildId ) { return pChild; }

	auto nChildren = GetChildrenCount(); for (decltype(nChildren) i = 0; i < nChildren; i++)
	{
		pChild = (*GetChildAt(i)); uId = pChild->UniqueId(); 
		if ( uId == uChildId ) { return pChild; }
	}

	decltype(pChild) pResult = nullptr; if ( bRecursively ) for (decltype(nChildren) i = 0; i < nChildren; i++)
	{
		pResult = (*GetChildAt(i))->FindById( uChildId, bRecursively );
		if ( pResult ) return pResult;
	}

	return nullptr;
}

Eifersucht::SceneChildPtr Eifersucht::SceneChild::FindByName( 
	_In_z_ Eifersucht::String8 szChildName, 
	_In_opt_ bool bRecursively 
	)
{
	auto pChild = this; String8 szName = pChild->GetName(); 
	if ( szName == szChildName ) { return pChild; }

	auto nChildren = GetChildrenCount(); for (decltype(nChildren) i = 0; i < nChildren; i++)
	{
		pChild = (*GetChildAt(i)); szName = pChild->GetName(); 
		if ( szName == szChildName ) { return pChild; }
	}

	decltype(pChild) pResult = nullptr; if ( bRecursively ) for (decltype(nChildren) i = 0; i < nChildren; i++)
	{
		pResult = (*GetChildAt(i))->FindByName( szChildName, bRecursively );
		if ( pResult ) return pResult;
	}

	return nullptr;
}